﻿using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Console : MonoBehaviour {
	public static string textstuff;

	//Assign these three to elements on a canvas. Console Window should be a panel and console text should be of similiar size. Just use the provided panel that comes with both
	//the panel, the text box, and the input field!

	public InputField edittext;
	public Image ConsoleWindow;	
	public Text ConsoleText;

	// Static reference to command menu so other scripts can call "tolog"
	public static Console Main;
	string memorize;
	float inputtimer;
	float waiittfooorriitt;
	bool activate;
	bool imready;
	int currenttextline;
	bool showfps;

	void Awake()
	{
		// Setting the static reference to whomever calls it. Note that if you set the object this is attached to to not die on load should probly destroy any clones of this class... It could get messy.
		Main = this;

		// Attempting to check for the components it needs, checking for missing parts.
		if (edittext == null)
		{
			edittext = GetComponentInChildren(typeof(InputField)) as InputField;
			if (edittext == null)
				Debug.LogError("Please either assign a Input field to the public variable \"edittext\" or (Reccomended) place the input field as a child of the object \""+gameObject.name+"\" that this script is attached to");
		}
		if (ConsoleWindow == null)
		{
			ConsoleWindow = GetComponentInChildren(typeof(Image)) as Image;
			if (ConsoleWindow.name != "Panel")
				Debug.LogError("The required component \"Image\" was found on the children, however the wrong one may have been selected since the name is not \"Panel\". If you do not see text in the console window, you need to assign the public variable ConsoleWindow manually");
			if (ConsoleWindow == null)
				Debug.LogError("Please either assign a Image/panel(The background of the console) to the public variable \"ConsoleWindow\" or (Reccomended) place the input field as a child of the object \""+gameObject.name+"\" that this script is attached to");
		}
		if (ConsoleText == null)
		{
			Debug.LogError("Cannot Manually find a textbox, please create a textbox on the UI to print text onto and then assign the variable ConsoleText to that textfield");
		}
	}

	void OnGUI()
	{
		// Using the command "/fps" will show the fps. I got this line of script online somewhere, not sure how accurate it is, just needed a FPS-show quick. Feel free to replace.
		if (showfps)
			GUI.Label(new Rect(500, 0, 100, 100), "yes" +(1.0f / Time.smoothDeltaTime));




	}

	//!!!!!!!! This whole update section is a mess, I think I understand this a bit more, ill try to work on it sometime, ignore it for now.

	void Update()
	{
		if (Input.GetKeyDown(KeyCode.BackQuote))
		{
			if (ConsoleWindow.gameObject.activeSelf)
				ConsoleWindow.gameObject.SetActive(false);
			else
			{
				activate = true;
			}
		}
		if (activate && Input.GetKey(KeyCode.Return) == false && Input.GetKeyDown(KeyCode.BackQuote) == false)
		{
			ConsoleWindow.gameObject.SetActive(true);
			edittext.interactable = true;
			edittext.ActivateInputField();
			EventSystem.current.SetSelectedGameObject(edittext.gameObject, null);
			edittext.OnPointerClick(new PointerEventData(EventSystem.current));
			activate = false;
			imready = true;
		}
		if (Input.GetKeyUp(KeyCode.Return) && Time.time > inputtimer && ConsoleWindow.gameObject.activeSelf)
		{
			if (imready == false)
			{
				activate = true;
				inputtimer = Time.time + 0.04f;
				waiittfooorriitt = 0;
			}
			else
			{
				{
					edittext.interactable = false;
					EventSystem.current.SetSelectedGameObject(null, null);
					edittext.OnPointerClick(new PointerEventData(EventSystem.current));
					memorize = edittext.text;
					textentered(edittext.text);
					edittext.DeactivateInputField();
					edittext.text = "";
					inputtimer = Time.time + 0.04f;
					edittext.DeactivateInputField();
					imready = false;
				}
			}
		}

		if (Input.GetKeyDown(KeyCode.UpArrow) && edittext.isFocused)
		{
			if (memorize == null)
				return;
			edittext.text = memorize;
		}
		if (edittext.isFocused == false && Time.time > inputtimer && imready == true)
		{
			waiittfooorriitt ++;
			if (waiittfooorriitt > 100)
			{
			edittext.interactable = false;
			EventSystem.current.SetSelectedGameObject(null, null);
			edittext.OnPointerClick(new PointerEventData(EventSystem.current));
			edittext.text = "";
			edittext.DeactivateInputField();
			imready = false;
			}
		}
	}

	/// <summary>
	/// Text entered into the consolebox. This checks for commands by checking for the /, removing it, and splitting the rest of the text into an array based on spaces.
	/// </summary>
	/// <param name="tex">String</param>
	void textentered(string tex)
	{
		// Creating Artificial delay to prevent spam or some wierd issue
		inputtimer = Time.time + 0.1f;

		// Obvious check is obvious
		if (tex.StartsWith("/"))
		{
			//Splitting the text from the slash
			string[] split = tex.Split('/');

			//Taking everything after the slash and making a new array from the spaces in it
			split = split[1].Split(' ');

			//Testing for the text after the slash Example below v
			/*			if (split[0] == "spawn" || split[0] == "Spawn" || split[0] == "s" || split[0] == "S")
//			{
//				if (split.Length < 2)
//				{
//					Debug.Log("Spawn what you mook?");
//					return;
//				}
//				Spawner.Enemy tospawn = Spawner.Enemy.None;
//				foreach(Spawner.Enemy test in System.Enum.GetValues(typeof(Spawner.Enemy)))
//				{
//					string temp = (string)test.ToString();
//					if (string.Compare(split[1], temp, ignoreCase:true) == 0)
//					{
//						tospawn = test;
//						edittext.text = "";
//						Spawner.SpawnToPlayer(tospawn, 3);
//						break;
//					}
//					else
//					{
//						int temp2;
//						if (System.Int32.TryParse(split[1], out temp2))
//						{
//							Spawner.SpawnToPlayer(Spawner.EnemyID(temp2), 3);
//							tospawn = Spawner.Enemy.Bug;
//							break;
//						}
//
//						
//					}
//				}
//				if (tospawn == Spawner.Enemy.None)
//				{
//					Debug.Log("No Match for /spawn");
//					edittext.text = "";
//					return;
//				}
//			}
*/

			// Sound test
			if (string.Compare(split[0], "sound", ignoreCase:true) == 0)
			{
				CommandSound(split);
			}

			//FPS test
			if (string.Compare(split[0], "fps", ignoreCase:true) == 0)
			{
				CommandFPS();
			}
		}

		else
		{
			if (tex != "")
				tolog(tex);
			edittext.text = "";
		}

		
	}

	/// <summary>
	/// Prints to the console log.
	/// </summary>
	/// <param name="text">Text.</param>
	public static void tolog(string text)
	{	
		//Trying to see what line we're on
		Main.currenttextline += 1;
		
		//Providing a warning for text to be cleared in a few lines once it reaches a certain point
		if (Main.currenttextline == 200)
		{
			Main.currenttextline = 201;
			Main.ConsoleText.text = Main.ConsoleText.text + "\n" + "<color=#0000ffff>Log will be cleared after 10 more lines!</color>";

		}
		
		//Clears text to save up on memory if the line exceeeds a certain limit. Could do this in a better way maybe. Maybe add a way to save a log, even?
		if (Main.currenttextline == 211)
		{
			Main.ConsoleText.text = "<color=#0000ffff>Console Log Cleared</color>";
			Main.currenttextline = 0;
		}

		// Prints the text to the console
		Main.ConsoleText.text = Main.ConsoleText.text + "\n"+text;
	}





	//Add all functions for commands passed this point





	void CommandSound(string[] split)
	{
		//Making sure theres more than just the command in the array.
		if (split.Length < 2)
		{
			Debug.Log("You didnt enter a sound ID number.");
			return;
		}
		if (split[1] == "list")
		{
			string gather = "";
			int iterate = 0;
			foreach (AudioClip clip in Sound.Main.sounds)
			{
				gather = gather + clip.name + "("+iterate+"), ";
				iterate ++;
			}
			tolog (gather);
			return;
		}
		if (split[1] == "info")
		{
			if (split.Length < 3)
			{
				Debug.Log("Please enter a clip ID to get info from");
				return;
			}
			int parsley;
			if (System.Int32.TryParse(split[2], out parsley))
			{
				if (parsley > Sound.Main.sounds.Length-1)
				{
					Debug.LogWarning("No sound by this ID exists");
					return;
				}
				AudioClip clipinfo = Sound.Main.sounds[parsley];
				string gather = "<b>ID:</b>"+parsley.ToString()+" "+"<color=#800000ff>NAME = </color>"+clipinfo.name+"<color=#800000ff> LENGTH = </color>"+clipinfo.length+"<color=#800000ff> SAMPLES = </color>"+clipinfo.samples;
				tolog(gather);
				return;
			}
		}
		int parased;
		if (System.Int32.TryParse(split[1], out parased))
		{
			if (Sound.PlaySound(parased))
			{
				tolog("You played the sound \""+Sound.Main.sounds[parased].name+"("+parased+")\"");
			}
		}
		else
		{
			if (Sound.PlaySound(split[1]))
			{
				tolog("You played the sound \""+split[1]+"\".");
			}
		}
	}
	void CommandFPS()
	{
		if (showfps)
			showfps = false;
		else
			showfps = true;
	}
}
